package dxn.nl.file.center.netty.consumer;

import dxn.boot.common.config.CsApplicationContext;
import dxn.nl.file.biz.po.FileDealServerPo;
import dxn.nl.file.biz.service.ExcelDealServerBaseService;
import dxn.nl.file.center.CsCenterNettyConstants;
import dxn.nl.file.center.SocketManager;
import io.netty.channel.socket.SocketChannel;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class ConsumerSocketManager {
    private static final Logger logger = LoggerFactory.getLogger(ConsumerSocketManager.class);
    public final static String exportDealServerAppName = "cms-export-deal-consumer";
    private static final HashMap<String, ConsumerChannelDto> registerMap = new HashMap<>();
    private static final HashMap<String, List<String>> consumerIdsMap = new HashMap<>();
    private static int currentIndex = 0;
    public static int centPort = 0;

    private static ExcelDealServerBaseService excelDealServerBaseService;

    private static ExcelDealServerBaseService getDealServerBaseService() {
        if(excelDealServerBaseService == null)
        {
            excelDealServerBaseService = CsApplicationContext.getBean(ExcelDealServerBaseService.class);
        }
        return excelDealServerBaseService;
    }

    public ConsumerSocketManager() {
    }

    public static boolean contains(String sessionId)
    {
        ConsumerChannelDto appRegisterUtil = registerMap.get(sessionId);
        if(appRegisterUtil == null)
        {
            return false;
        }
        return true;
    }

    public static void addClient(String sessionId ,SocketChannel channel)
    {
        channel.attr(CsCenterNettyConstants.APP_ID).set(exportDealServerAppName);
        channel.attr(CsCenterNettyConstants.APP_SESSION_ID).set(sessionId);

        ConsumerChannelDto channelDto = new ConsumerChannelDto();
        channelDto.setChannel(channel);
        channelDto.setRegisterTime(LocalDateTime.now());
        channelDto.setRefreshTime(LocalDateTime.now());

        registerMap.put(sessionId,channelDto);

        try {
            FileDealServerPo fileDeal = new FileDealServerPo();
            fileDeal.setIp(channel.remoteAddress().getHostString());
            fileDeal.setPort(channel.remoteAddress().getPort());
            fileDeal.setSessionId(sessionId);
            fileDeal.setCentIp(SocketManager.getIp());
            fileDeal.setCentPort(centPort);
            fileDeal.setRefreshTime(LocalDateTime.now());
            fileDeal.setRegisterTime(LocalDateTime.now());
            ExcelDealServerBaseService service = getDealServerBaseService();
            service.saveFileDealServer(fileDeal);
        }
        catch (Exception e)
        {
            logger.error("",e);
        }
    }

    public static void removeClient(String sessionId)
    {
        ConsumerChannelDto appRegisterUtil = registerMap.get(sessionId);
        if(appRegisterUtil == null)
        {
            return ;
        }

        registerMap.remove(sessionId);

        try {
            ExcelDealServerBaseService service = getDealServerBaseService();
            service.removeDealServer(sessionId);
        }
        catch (Exception e)
        {
            logger.error("",e);
        }
    }

    public static void refreshClient(String sessionId)
    {
        ConsumerChannelDto appRegisterUtil = registerMap.get(sessionId);
        if(appRegisterUtil == null)
        {
            return ;
        }
        appRegisterUtil.setRefreshTime(LocalDateTime.now());
        try {
            ExcelDealServerBaseService service = getDealServerBaseService();
            service.refreshDealServer(sessionId,LocalDateTime.now());
        }
        catch (Exception e)
        {
            logger.error("",e);
        }
    }

    public static SocketChannel getChannel(String sessionId)
    {
        if(StringUtils.isNotBlank(sessionId))
        {
            ConsumerChannelDto appRegisterUtil = registerMap.get(sessionId);
            if(appRegisterUtil == null)
            {
                return null;
            }

            if(appRegisterUtil.getChannel()!=null && !appRegisterUtil.getChannel().isActive())
            {
                registerMap.remove(sessionId);
                return null;
            }
            return appRegisterUtil.getChannel();
        }

        ConsumerChannelDto appRegisterUtil = null;
        currentIndex = (currentIndex + 1) % registerMap.size();
        int i=0;
        for(Map.Entry<String,ConsumerChannelDto> entry:registerMap.entrySet())
        {
            if(i>=currentIndex)
            {
                appRegisterUtil = entry.getValue();
                sessionId = entry.getKey();
            }
        }

        if(appRegisterUtil == null)
        {
            return null;
        }

        if(appRegisterUtil.getChannel()!=null && !appRegisterUtil.getChannel().isActive())
        {
            registerMap.remove(sessionId);
            try {
                appRegisterUtil.getChannel().close();
            }
            catch (Exception ex)
            {
                logger.warn("",ex);
            }
            return getChannel(null);
        }

        return appRegisterUtil.getChannel();
    }
}
